package com.geng.invoker;


import com.geng.connect.ChannelPara;
import com.geng.connect.DCConnect;
import com.geng.connect.IConnectStrategy;
import com.geng.connect.ZKConnect;
import com.geng.dto.InvokerService;
import com.geng.dto.ProviderService;
import com.geng.zkORdc.IRegisterCenter4Invoker;
import com.geng.zkORdc.RegisterCenter;
import org.apache.commons.collections.MapUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;

import java.net.InetSocketAddress;
import java.util.List;
import java.util.Map;


/**
 * @author geng
 */
public class InvokerFactoryBean implements FactoryBean, InitializingBean {

    /**
     * 服务接口
     */
    private Class<?> targetInterface;
    /**
     * 超时时间
     */
    private int timeout;
    /**
     * 服务bean
     */
    private Object serviceObject;
    /**
     * 负载均衡策略
     */
    private String clusterStrategy;
    /**
     * 服务提供者唯一标识
     */
    private String remoteAppKey;
    /**
     * 服务分组组名
     */
    private String groupName = "default";

    /**
     * 是采用直连还是注册中心，0表示直连，1zk
     * 服务端就不那么复杂了，因为注册中心没有改
     * @return
     */
    private int connectFlag;

    /**
     * 传递一个socket
     */
    private String socket;


    @Override
    public Object getObject() throws Exception {
        return serviceObject;
    }

    @Override
    public Class<?> getObjectType() {
        return targetInterface;
    }


    @Override
    public boolean isSingleton() {
        return true;
    }

    //在bean完成初始化后做自己的操作,可以在这进行直连
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InvokerFactoryBean: " + this);

        //从注册中心获取服务
        ProviderService providerService = new ProviderService();

        //得到策略
        IConnectStrategy connectStrategy = getConnectStrategy(providerService);

        ChannelPara channelPara = new ChannelPara.Builder()
                .groupName(groupName)
                .remoteAppKey(remoteAppKey)
                .socket(socket)
                .build();

        connectStrategy.registeChannel(channelPara);

        //得到代理工厂
        InvokerProxy proxyFactory = getProxyFactory(connectStrategy);

        this.serviceObject = proxyFactory.getProxy();
    }

    private IConnectStrategy getConnectStrategy(ProviderService providerService){
        IConnectStrategy connectStrategy = null;

        if(connectFlag == 0){
            connectStrategy = new DCConnect.Builder()
                    .providerService(providerService)
                    .targetInterface(targetInterface)
                    .build();
        }else{
            connectStrategy = new ZKConnect.Builder()
                    .clusterStrategy(clusterStrategy)
                    .providerService(providerService)
                    .targetInterface(targetInterface)
                    .build();
        }
        return connectStrategy;
    }

    private InvokerProxy getProxyFactory(IConnectStrategy connectStrategy) throws Exception {
         return InvokerProxy.newInvokerProxyBeanFactory(connectStrategy,timeout,targetInterface);
    }

    public Class<?> getTargetInterface() {
        return targetInterface;
    }

    public void setTargetInterface(Class<?> targetInterface) {
        this.targetInterface = targetInterface;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public Object getServiceObject() {
        return serviceObject;
    }

    public void setServiceObject(Object serviceObject) {
        this.serviceObject = serviceObject;
    }

    public String getClusterStrategy() {
        return clusterStrategy;
    }

    public void setClusterStrategy(String clusterStrategy) {
        this.clusterStrategy = clusterStrategy;
    }

    public String getRemoteAppKey() {
        return remoteAppKey;
    }

    public void setRemoteAppKey(String remoteAppKey) {
        this.remoteAppKey = remoteAppKey;
    }

    public String getGroupName() {
        return groupName;
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    public int getConnectFlag() {
        return connectFlag;
    }

    public void setConnectFlag(int connectFlag) {
        this.connectFlag = connectFlag;
    }

    public String getSocket() {
        return socket;
    }

    public void setSocket(String socket) {
        this.socket = socket;
    }
}
